package com.waypolice.common.utils;

import net.sf.json.JSONObject;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;


/**
 * http请求工具类
 * @author 312小时
 * Created by 312小时 on 2018/8/23.
 */
public class HttpClientUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    public static String httpReader(String url, String code){
//        logger.info("URL------------>:"+url);
        HttpClient client = new HttpClient();
        GetMethod method = new GetMethod(url);

        String result = null;
        try {
            client.executeMethod(method);
            int status = method.getStatusCode();
            if (status == HttpStatus.SC_OK) {
                result = method.getResponseBodyAsString();
            } else {
                logger.info("Method failed---------------------------->: " + method.getStatusLine());
            }
        } catch (HttpException e) {
            // 可能是协议不对或者返回的内容有问题
            logger.info("发生HTTP异常，可能是协议不对或者返回的内容有问题!");
            logger.error(e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            // 发生网络异常
            logger.info("发生IO异常！");
            logger.error(e.getMessage());
            e.printStackTrace();
        } finally{
            // 释放连接
            if(method!=null){
                method.releaseConnection();
            }
            method = null;
            client = null;
        }
        return result;
    }

    /**
     * get请求
     * @param url
     * @param code
     * @return
     */
    public static String httpGet(String url,String code) {
        logger.info("GetPage:"+url);
        String content = null;
        HttpClient httpClient = new HttpClient();
        //设置header
        httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT,"Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2");
        GetMethod method = new GetMethod(url);
        try {
            int statusCode = httpClient.executeMethod(method);
            logger.info("httpClientUtils::statusCode="+statusCode+"  "+method.getStatusLine());
            content = new String(method.getResponseBody(), code);

        } catch (Exception e) {
            logger.info("请求失败！");
            e.printStackTrace();
        } finally {
            if(method!=null){
                method.releaseConnection();
            }
            method = null;
            httpClient = null;
        }
        return content;
    }

    /**
     * post请求（用于key-value格式的参数）
     * @param url
     * @param paramMap
     * @param code
     * @return
     */
    public static JSONObject httpPost(String url, Map paramMap, String code) {
//        logger.info("URL-------------------------------------->:"+url);
        String content = null;
        if (url == null || url.trim().length() == 0 || paramMap == null|| paramMap.isEmpty()){
            return null;
        }
        HttpClient httpClient = new HttpClient();

        //设置header
        //httpClient.getParams().setParameter(HttpMethodParams.USER_AGENT,"Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2");

        //代理设置
        //httpClient.getHostConfiguration().setProxy("128.128.176.74", 808);
        PostMethod method = new PostMethod(url);
        Iterator it = paramMap.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next() + "";
            Object o = paramMap.get(key);
            if (o != null && o instanceof String) {
                method.addParameter(new NameValuePair(key, o.toString()));
            }
            if (o != null && o instanceof String[]) {
                String[] s = (String[]) o;
                if (s != null){
                    for (int i = 0; i < s.length; i++) {
                        method.addParameter(new NameValuePair(key, s[i]));
                    }
                }
            }
        }
        try {
            HttpMethodParams param = method.getParams();
            param.setContentCharset("UTF-8");
            int statusCode = httpClient.executeMethod(method);
            method.getResponseBodyAsStream();
//            logger.info("----------------------------------->请求状态::statusCode="+statusCode+"  "+method.getStatusLine());
            content = new String(method.getResponseBody(), code);

        } catch (Exception e) {
            logger.info("------------------------------------------->请求失败！");
            e.printStackTrace();
        } finally {
            if(method!=null){
                method.releaseConnection();
            }
            method = null;
            httpClient = null;
        }
        return JSONObject.fromObject(content);
    }
    /**
     * post请求（用于json格式的参数）
     * @param url
     * @param params
     * @return
     */
    public static JSONObject doPost(String url, String params) throws Exception {
        logger.info("*********************post请求开始******************"+params);
        final String APPLICATION_JSON = "application/json";
        final String CONTENT_TYPE_TEXT_JSON = "text/json";
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httpPost
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-Type", "application/json");
        String charSet = "UTF-8";
        StringEntity entity = new StringEntity(params, charSet);
        entity.setContentType(APPLICATION_JSON);
        httpPost.setEntity(entity);
        CloseableHttpResponse response = null;
        JSONObject jsonObject = null;
        try {
            response = httpclient.execute(httpPost);
            StatusLine status = response.getStatusLine();
            int state = status.getStatusCode();
            String newUri="";
            //判断是否为重定向
            if(state == 302){
                logger.info("************************************接口的请求地址被重定向****************************************************************");
                //跳转重定向的地址在HTTP-HEAD中
                Header header = response.getFirstHeader("location");
                //跳转重定向后的地址
                newUri=header.getValue();
                logger.info("************************************重定向后的地址**************************************************************************");
                logger.info(newUri);
                logger.info("************************************向重定向后的地址发出新的请求，获取重定向后的具体信息***************************************");
                //向重定向后的地址发出新的请求，获取重定向后的具体信息
                httpPost=new HttpPost(newUri);
                httpPost.setHeader("Accept","application/json");
                httpPost.setHeader("Content-Type","application/json;charset=UTF-8");
                entity=new StringEntity(params);
                entity.setContentType(APPLICATION_JSON);
                httpPost.setEntity(entity);
                response=httpclient.execute(httpPost);
                int flag=response.getStatusLine().getStatusCode();
                logger.info("**********************************************重定向后的信息**************************************");
                logger.info("状态status:--- "+flag+" 信息----- "+response);
                logger.info("***************************************************************************************************");
            }
            else if (state == HttpStatus.SC_OK) {
                logger.info("******************POST银行接口调用正常************"+state);
                HttpEntity responseEntity = response.getEntity();
                String jsonString = EntityUtils.toString(responseEntity);
                jsonObject = JSONObject.fromObject(jsonString);
                logger.info("********************POST银行接口返回数据******************"+jsonObject.toString());
                return jsonObject;
            }
            else{
                logger.error("请求失败-----返回:"+state+"("+url+")");
            }
        }
        finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonObject;
    }
    public static JSONObject httpPost(String url, Map paramMap) {
        //编码：UTF-8
        return HttpClientUtil.httpPost(url, paramMap, "UTF-8");
    }

    /**
     * @author:zyp
     * @description httpClient关闭流
     * @date: 2018/9/25 13:44
     * @return 
     */
    public static void closeQuietly(Closeable closeable){
        if(closeable!=null){
            try {
                closeable.close();
            } catch (IOException e) {
                logger.info("httpClient关闭流失败！");
                e.printStackTrace();
            }
        }
    }

    /**
     * @author:zyp
     * @description httpClient文件上传
     * @date: 2018/9/25 14:14
     * @return
     * @param url web路径
     * @param key 密钥
     * @param fileUrl 文件的地址
     */
    public static JSONObject fileUpload(String url,String key,String fileUrl,String fileName){
        String keyMD5 = CheckUrlCodeUtil.getMD5WithRSASign(key);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        JSONObject jsonObject = null;
        try{
            // 要上传的文件的路径
            String filePath =new String(fileUrl);
            // 把一个普通参数和文件上传给下面这个地址 是一个servlet
            HttpPost httpPost =new HttpPost(url);
            // 把文件转换成流对象FileBody
            File file =new File(filePath);
            FileBody bin =new FileBody(file);
            StringBody sign = new StringBody(keyMD5, ContentType.create("text/plain", Consts.UTF_8));
            StringBody content = new StringBody(key, ContentType.create("text/plain", Consts.UTF_8));
            StringBody name = new StringBody(fileName, ContentType.create("text/plain", Consts.UTF_8));
            //以浏览器兼容模式运行，防止文件名乱码。
            HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                    //uploadFile对应服务端类的同名属性<File类型>
                    .addPart("uploadFile", bin)
                    //uploadFileName对应服务端类的同名属性<String类型>
                    .addPart("sign",sign)
                    .addPart("content",content)
                    .addPart("fileName",name)
                    .setCharset(CharsetUtils.get("UTF-8")).build();
            httpPost.setEntity(reqEntity);
            logger.info("发起请求的页面地址 "+ httpPost.getRequestLine());
            // 发起请求 并返回请求的响应
            response = httpClient.execute(httpPost);
            logger.info("----------------------------------------");
            // 打印响应状态
            logger.info("发起请求的响应状态  :  "+response.getStatusLine());
            // 获取响应对象
            HttpEntity resEntity = response.getEntity();
            if(resEntity !=null) {
                // 打印响应长度
                logger.info("Response content length: " + resEntity.getContentLength());
                //返回的数据
                String entity = EntityUtils.toString(resEntity,Charset.forName("UTF-8"));
                // 打印响应内容
                logger.info(entity);
                jsonObject = JSONObject.fromObject(entity);
                logger.info("********************上传对账订单文件返回数据******************"+jsonObject.toString());
            }
            // 销毁
            EntityUtils.consume(resEntity);
        }catch(Exception e){
            logger.error("发送文件失败!!!");
            e.printStackTrace();
        }finally{
            HttpClientUtil.closeQuietly(response);
            HttpClientUtil.closeQuietly(httpClient);
        }
        return jsonObject;
    }

    /**
     * @author:zyp
     * @description  httpClient文件下载
     * @date: 2018/9/25 15:17
     * @return 
     */
    public static void downFile(String url,String key,String fileUrl,String fileName){
        logger.info("下载后的文件地址 "+ fileUrl);
        String keyMD5 = CheckUrlCodeUtil.getMD5WithRSASign(key);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        FileOutputStream fout = null;
        InputStream in = null;
        try {
            HttpPost httpPost =new HttpPost(url);
            StringBody sign = new StringBody(keyMD5, ContentType.create("text/plain", Consts.UTF_8));
            StringBody content = new StringBody(key, ContentType.create("text/plain", Consts.UTF_8));
            StringBody name = new StringBody(fileName, ContentType.create("text/plain", Consts.UTF_8));
            //以浏览器兼容模式运行，防止文件名乱码。
            HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                    .addPart("sign",sign)
                    .addPart("content",content)
                    .addPart("fileName",name)
                    .setCharset(CharsetUtils.get("UTF-8")).build();
            httpPost.setEntity(reqEntity);
            logger.info("发起请求的页面地址 "+ httpPost.getRequestLine());
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            in = entity.getContent();
            File file =new File(fileUrl);
            fout =new FileOutputStream(file);
            int len = -1;
            byte[] tmp =new byte[1024];
            while((len = in.read(tmp)) != -1) {
                fout.write(tmp,0, len);
                // 注意这里如果用OutputStream.write(buff)的话，图片会失真，大家可以试试
            }
            fout.flush();
            // 销毁
            EntityUtils.consume(entity);
        } catch (IOException e) {
            logger.error("http下载对账文件失败！");
            e.printStackTrace();
        }finally {
            IoUtils.closeOutputStram(fout);
            IoUtils.closeInputStram(in);
            HttpClientUtil.closeQuietly(httpclient);
        }
    }
}
